package com.cnswhy.cloud.server.app.controller.shop;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.core.utils.SystemClockUtil;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.app.config.JsApiPay;
import com.cnswhy.cloud.server.app.config.WxPayApi;
import com.cnswhy.cloud.server.app.config.WxPayData;
import com.cnswhy.cloud.server.app.controller.BaseController;
import com.cnswhy.cloud.server.app.utils.KdniaoUtils;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.OrderPfxEnum;
import com.cnswhy.cloud.server.common.entity.enumeration.PayType;
import com.cnswhy.cloud.server.common.entity.mq.OrderQueryMQ;
import com.cnswhy.cloud.server.core.channel.service.AliRoutePayService;
import com.cnswhy.cloud.server.core.service.ShopOrderReceiverService;
import com.cnswhy.cloud.server.core.shop.ProductStockService;
import com.cnswhy.cloud.server.core.utils.PasswordCoder;
import com.cnswhy.cloud.server.app.utils.RSAUtils;
import com.cnswhy.cloud.server.common.entity.enumeration.WalletType;
import com.cnswhy.cloud.server.core.config.AlipayConfig;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import com.cnswhy.cloud.server.core.entity.ShopOrderDetail;
import com.cnswhy.cloud.server.core.dto.*;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.query.QueryGenerator;
import com.cnswhy.cloud.server.core.service.ShopOrderDetailService;
import com.cnswhy.cloud.server.core.service.SysConfigService;
import com.cnswhy.cloud.server.core.service.customer.CustomerReceiverService;
import com.cnswhy.cloud.server.core.service.customer.CustomerService;
import com.cnswhy.cloud.server.core.service.merchant.MerchantService;
import com.cnswhy.cloud.server.core.service.shop.ShopOrderService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductStockService;
import com.cnswhy.cloud.server.core.vo.RespVo;
import com.cnswhy.cloud.server.core.wallet.WalletService;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

/**
 * 描述: 名品名店订单
 * 版权: Copyright (c) 2019
 * 公司: 小鹿科技
 * 作者: 张润泽
 * 版本: 1.0
 * 创建日期: 2019年8月13日
 * 创建时间: 下午7:30:46
 */
@Api(tags = "商品订单控制层")
@Controller
@RequestMapping("/shop/order")
@Slf4j
public class ShopOrderController extends BaseController {

    @Autowired
    IdGeneratorService idGeneratorService;
    @Autowired
    private ShopOrderService shopOrderService;

    @Autowired
    private ShopProductService shopProductService;

    @Autowired
    private CustomerService customerService;


    @Autowired
    private CustomerReceiverService customerReceiveService;


    @Autowired
    private RedisService redisService;
    @Autowired
    MerchantService merchantService;
    @Autowired
    ShopProductStockService shopProductStockService;

    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    WalletService walletService;
    @Autowired
    ShopOrderDetailService shopOrderDetailService;
    @Autowired
    private MessageService messageService;
    @Autowired
    ProductStockService productStockService;
    @Autowired
    AliRoutePayService aliRoutePayService;
    @Autowired
    ShopOrderReceiverService shopOrderReceiverService;
    /**
     * 描述：确认获取确认订单商品列表
     * 作者：张润泽
     * 时间：2019年8月29日 上午10:10:12
     *
     * @param itemJson
     * @param request
     * @return
     */
    @ApiOperation(value = "暂时无用", httpMethod = "POST")
    @RequestMapping("/getConfirmOrder")
    @ResponseBody
    public RespVo getConfirmOrder(String itemJson, Long receiverId, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            List<BuyerOperateBo> list = JSON.parseArray(itemJson, BuyerOperateBo.class);
            BuyerCart buyerCart = shopOrderService.getBuyerCart(list, customerReceiveService.getById(receiverId));
            respVo.setResult(buyerCart);
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("成功");
            return respVo;
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("失败");
            log.error("名品名店查询确认订单商品列表异常：", e);
        }
        return respVo;
    }

    /**
     * 描述：计算订单金额
     * 作者：张润泽
     * 时间：2019年8月29日 上午10:10:12
     *
     * @param
     * @param request
     * @return
     */
    @ApiOperation(value = "计算价格", httpMethod = "POST")
    @RequestMapping("/countPrice")
    @ResponseBody
    public RespVo countPrice(Long stockId, Integer num, BigDecimal useIntegral, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            log.error("===========参数信息：useIntegral :  " + useIntegral);
            ShopProductStock stock = shopProductStockService.getById(stockId);

            // 计算订单总额
            BigDecimal total = stock.getSellPrice().multiply(new BigDecimal(num));
            String rate = "0";
            if (useIntegral.compareTo(BigDecimal.ZERO) > 0) {
                rate = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.USE_INTEGRAL_DECUTION);
                total = total.subtract(useIntegral.multiply(new BigDecimal(rate)));
            }

            respVo.setResult(total);
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("成功");
            return respVo;
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("失败");
            log.error("名品名店计算订单金额异常：", e);
        }
        return respVo;
    }

    /**
     * 描述：下单
     * 作者：张润泽
     * 时间：2019年8月29日 上午10:14:53
     *
     * @param makeOrderJson
     * @param request
     * @return
     */
    @ApiOperation(value = "下单")
    @ApiParam(name = "makeOrderJson", value = "下单json字符串")
    @RequestMapping("/makeOrder")
    @ResponseBody
    public RespVo makeOrder(String makeOrderJson, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            Customer loginCustomer = getLoginCustomer( request);
            MakeOrderBo bo = JSON.parseObject(makeOrderJson, MakeOrderBo.class);
            bo.setCustomerId(loginCustomer.getId());
            bo.setCustomer(customerService.queryById(loginCustomer.getId()));
            bo.setReceiver(customerReceiveService.getById(bo.getReceiverId()));
            if (bo.getPayType() == 3 || bo.getPayType() == 4 || bo.getPayType() == 5 || bo.getPayType() == 6) {
                if (StringUtils.isNotBlank(bo.getTradePass())) {
                    String password = null;
                    password = RSAUtils.decryptString(bo.getTradePass());// 解密

                    if (!StringUtils.equals(PasswordCoder.generatePassword(password), bo.getCustomer().getTradePass())) {
                        respVo.setCode(RespVo.CODE_ERROR);
                        respVo.setMessage("交易密码错误");
                        return respVo;
                    }
                } else {
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("请输入交易密码");
                    return respVo;
                }
            }

            return saveOrder(bo);
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("下单失败");
            log.error("下单异常：", e);
        }
        return respVo;
    }


    /**
     * 描述：查询当前登录用户所有订单列表
     * 作者：张润泽
     * 时间：2019年8月13日 下午8:49:08
     *
     * @param bo
     * @param request
     * @return
     */
    @ApiOperation(value = "查询订单列表", httpMethod = "POST")
    @ApiParam(name = "bo", value = "订单BO对象")
    @RequestMapping("/ajaxPage")
    @ResponseBody
    public RespVo ajaxPage(ShopOrder bo,
                           @RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                           @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
//            CurrentCustomer currentUser = this.getCurrentUser(request);
            Customer loginCustomer = getLoginCustomer( request);
            bo.setCustomerId(loginCustomer.getId());
            QueryWrapper<ShopOrder> queryWrapper = QueryGenerator.initQueryWrapper(bo);
            queryWrapper.orderByDesc("create_time");
            Page<ShopOrder> page = new Page<>(currentPage, pageSize);
            IPage<ShopOrder> pageList = shopOrderService.page(page, queryWrapper);
            for(ShopOrder shopOrder : pageList.getRecords()){
               /* shopOrder.setShopOrderReceiver();
                List<ShopOrderDetail> detailList = shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId, shopOrder.getId()));

                shopOrder.setShopOrderDetails(detailList);*/
                shopOrder.setShopOrderDetails(shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId,shopOrder.getId())));
                shopOrder.setShopOrderReceiver(shopOrderReceiverService.getOne(Wraps.<ShopOrderReceiver>lbQ().eq(ShopOrderReceiver::getOrderId,shopOrder.getId())));
                shopOrder.setCustomer(customerService.getById(shopOrder.getCustomerId()));
            }
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("查询成功");
            respVo.setResult(pageList);
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("查询失败");
            log.error("查询名品名店订单列表异常：", e);
        }
        return respVo;
    }
/*
    @ApiOperation(value = "查询订单列表", httpMethod = "POST")
    @ApiParam(name = "bo", value = "订单BO对象")
    @RequestMapping("/ajaxPageShopOrder")
    @ResponseBody
    public RespVo ajaxPageShopOrder(ShopOrder bo, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            Customer loginCustomer = getLoginCustomer( request);
            bo.setCustomerId(loginCustomer.getId());
            List<ShopOrder> pageList = shopOrderService.pageList(bo);
            String prefix = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX);
            JSONObject object = new JSONObject();
            object.put("pageList", pageList);
            object.put("photosUrl", "");
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("查询成功");
            respVo.setResult(object);
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("查询失败");
            log.error("查询名品名店订单列表异常：", e);
        }
        return respVo;
    }*/

//    @RequestMapping("/ajaxChildPage")
//    @ResponseBody
//    public RespVo ajaxChildPage(ShopOrderBo bo, HttpServletRequest request)
//    {
//        RespVo respVo = new RespVo();
//        try
//        {
//            CustomerEntity loginCustomer = getLoginCustomer( request);
//            bo.setCurrentCustomer(loginCustomer.getId());
//            PagerVo<ShopOrder> queryPageData = shopOrderService.queryPage(bo);
//            respVo.setCode(RespVo.CODE_SUCCESS);
//            respVo.setMessage("查询成功");
//            respVo.setResult(queryPageData);
//        }
//        catch (Exception e)
//        {
//            respVo.setCode(RespVo.CODE_ERROR);
//            respVo.setMessage("查询失败");
//            log.error("查询名品名店订单列表异常：", e);
//        }
//        return respVo;
//    }

    /**
     * 描述：查询订单详情
     * 作者：张润泽
     * 时间：2019年8月13日 下午8:49:08
     *
     * @param id
     * @param request
     * @return
     */
    @ApiOperation(value = "查询订单详情", httpMethod = "POST")
    @ApiParam(name = "id", value = "订单id", required = true)
    @RequestMapping("/detail")
    @ResponseBody
    public RespVo detail(Long id, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            if (id == null) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("参数异常");
                return respVo;
            }

            respVo.setResult(shopOrderService.queryById(id));
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("查询成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("查询失败");
            log.error("查询名品名店订单详情异常：", e);
        }
        return respVo;
    }

    /**
     * 描述：变更订单状态：取消订单、申请退款、确认收货
     * 作者：张润泽
     * 时间：2019年8月13日 下午8:49:08
     *
     * @param id
     * @param productIds 产品id列表
     * @param status     1-取消订单 2-申请退款 3-确认收货
     * @param refundDesc 原因
     * @param request
     * @return
     */
    @ApiOperation(value = "更新状态", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单id"),
            @ApiImplicitParam(name = "productIds", value = "商品id"),
            @ApiImplicitParam(name = "status", value = "状态"),
            @ApiImplicitParam(name = "refundDesc", value = "退货原因")
    })
    @RequestMapping("/updateStatus")
    @ResponseBody
    public RespVo updateStatus(Long id, String productIds, Integer status, String refundDesc,
                               HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            if (id == null || status == null || status > 3 || status < 1
                    || (status < 3 && StringUtils.isBlank(refundDesc))) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("参数异常");
                return respVo;
            }

            ShopOrder order = shopOrderService.queryById(id);
            if (order == null) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("订单不存在");
                return respVo;
            }

            // 只有状态在1-待付款时，才能取消订单
            if (status == 1 && !order.getStatus().equals(1)) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("订单不是待付款状态，无法取消");
                return respVo;
            }

            // 只有状态在2-待发货 3-待收货 4-待评价时，才能申请退款
            if (status == 2 && (order.getStatus() < 2 || order.getStatus() > 4)) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("订单无法申请退款");
                return respVo;
            }

            // 只有状态在3-待收货时，才能确认收货
            if (status == 3 && !order.getStatus().equals(3)) {
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("订单不是待收货状态，无法确认收货");
                return respVo;
            }
            if (status == 2 && order.getPayType() == 3) {
                //纯购物券支付的订单不能退货
                respVo.setCode(RespVo.VALIDATE_ERROR);
                respVo.setMessage("秒杀区商品不能退货");
                return respVo;
            }
            updateOrderStatus(order, productIds, status, refundDesc);
//            if (status == 2)
//            {
//                // 退款消息提醒
//                JSONObject obj = new JSONObject();
//                obj.put("orderNum", order.getOrderNo());
//                MerchantInfo merchant = merchantService.queryMerchantById(order.getMerchantId());
//                SendSmsUtil.sendSms(merchant.getContactsTel(), "SMS_175533623", obj.toJSONString());
//            }
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("失败");
            log.error("修改名品名店订单状态异常：", e);
        }
        return respVo;
    }

    public void updateOrderStatus(ShopOrder order, String productIds, Integer status, String refundDesc) {
        ShopOrder entity = new ShopOrder();
        entity.setId(order.getId());

        //List<ShopOrderDetail> detailList = order.getDetailList();
        List<ShopOrderDetail> detailList = shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId, order.getId()));
        // 取消订单
        if (status == 1) {
            entity.setStatus(6);
            entity.setCancelDesc(refundDesc);
            entity.setFinishTime(SystemClockUtil.getLocalDateTime());
            shopOrderService.updateById(entity);
        }
        // 退款
        else if (status == 2) {
            // 若订单只有一个商品或整单退款，则将订单改为退款中
            if (detailList.size() == 1 || StringUtils.isBlank(productIds)) {
                entity.setStatus(8);
                entity.setPayOrderId(order.getId());
                entity.setRefundApplyDesc(refundDesc);
                entity.setRefundApplyTime(SystemClockUtil.getLocalDateTime());
                shopOrderService.updateById(entity);
            }
            // 若订单有多个商品且部分退款，则创建一个退款单
            else {
                String productArr[] = productIds.split(",");
                List<ShopOrderDetail> refundDetailList = shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId, entity.getId()));
                // 将支付订单中的商品状态改为退款中
                BigDecimal refundOrderPrice = BigDecimal.ZERO;
                for (ShopOrderDetail detail : detailList) {
                    for (String product : productArr) {
                        if (Long.valueOf(product).equals(detail.getId())) {
                            // 计算退款金额
                            refundOrderPrice = refundOrderPrice
                                    .add(detail.getAmount().multiply(new BigDecimal(detail.getNum())));

                            // 放入待退款商品列表
                            refundDetailList.add(detail);

                            // 更改支付单商品状态
                            detail.setStatus(3);
                            shopOrderDetailService.save(detail);
                            break;
                        }
                    }
                }

                // 创建一个退款单
                ShopOrder refundOrder = new ShopOrder();
                BeanUtils.copyProperties(order, refundOrder);
                refundOrder.setOrderNo(idGeneratorService.genCommonIdString());
                refundOrder.setStatus(8);
                refundOrder.setPayOrderId(order.getId());
                refundOrder.setRefundApplyDesc(refundDesc);
                refundOrder.setRefundApplyTime(SystemClockUtil.getLocalDateTime());
                refundOrder.setOrderPrice(refundOrderPrice);
                shopOrderService.save(refundOrder);
                // 保存商品详情
                if (CollUtil.isNotEmpty(refundDetailList)) {
                    for (ShopOrderDetail detail : refundDetailList) {
                        detail.setStatus(3);
                        detail.setOrderId(refundOrder.getId());
                        shopOrderDetailService.save(detail);
                    }
                }
            }
        }
        // 确认收货
        else {
            entity.setStatus(4);
            entity.setReceiveTime(SystemClockUtil.getLocalDateTime());
            shopOrderService.updateById(entity);
        }
    }

    /**
     * 描述：查询物流信息
     * 作者：张润泽
     * 时间：2019年9月17日 上午10:27:15
     *
     * @param expressNo 订单id
     * @param request
     * @return
     */
    @ApiOperation(value = "查询物流", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "expressNo", value = "物流单号"),
            @ApiImplicitParam(name = "expressCompany", value = "物流公司")
    })
    @RequestMapping("/queryLogistics")
    @ResponseBody
    public RespVo queryLogistics(String expressNo, String expressCompany, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            String result = KdniaoUtils.getResult(expressCompany, expressNo);
            respVo.setResult(JSONObject.parseObject(result));
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("失败");
            log.error("查询名品名店订单物流信息异常：", e);
        }
        return respVo;
    }


    @ApiOperation(value = "商城订单支付宝支付")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/alipayPay")
    @ResponseBody
    public RespVo alipayPay(HttpServletRequest request, HttpServletResponse response, String orderNum) {
        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            String price = "";
            String body = "SHOPPING";
            String flag = (String) redisService.hget(RedisConstant.SYS_CONFIG_2,
                    RedisConstant.ali_route_pay);
            if("true".equals(flag)) {
                ShopOrder queryByOrderNo = shopOrderService.queryByPayOrderNo(orderNum);
                queryByOrderNo.setChannelOrderId(idGeneratorService.genCommonIdString());
                shopOrderService.updateById(queryByOrderNo);
                try {
                    String responseString = aliRoutePayService.pay(queryByOrderNo.getChannelOrderId(), CnswhyUtil.getFen(queryByOrderNo.getOrderPrice()), "SHOPPING");
                    JSONObject jsonObject = JSON.parseObject(responseString);
                    if ("0100".equals(jsonObject.getString("code"))) {
                        String data = jsonObject.getString("data");
                        JSONObject jsonObject1 = JSON.parseObject(data);
                        respVo.setResult(jsonObject1.getString("html"));
                        respVo.setCode(RespVo.CODE_SUCCESS);
                        OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(queryByOrderNo.getChannelOrderId()).queryTimes(0L).build();
                        orderQueryMQ.setPayType(PayType.alipay);
                        orderQueryMQ.setBody("SHOPPING");
                        orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                        messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                        return respVo;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("调用支付宝发起支付请求异常");
                    return respVo;
                }
            }else {
                ShopOrder queryByOrderNo = shopOrderService.queryByPayOrderNo(orderNum);
                //ShopOrder queryByOrderNo = shopOrderService.getOne(Wraps.<ShopOrder>lbQ().eq(ShopOrder::getPayOrderNo, orderNum));
                queryByOrderNo.setChannelOrderId(idGeneratorService.genCommonIdString());
                shopOrderService.updateById(queryByOrderNo);

                //取库中支付宝参数
                SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys").eq(SysConfig::getDisplayStatus, "1"));

                price = queryByOrderNo.getOrderPrice().toString();
                AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, sysConfig.getConfigValue(),
                        sysConfig.getValidateRules(), AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                        sysConfig.getConfigRules(), AlipayConfig.SIGNTYPE);
                // AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

                AlipayTradeAppPayRequest alipay_request = new AlipayTradeAppPayRequest();
                // 封装请求支付信息
                AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
                model.setOutTradeNo(queryByOrderNo.getChannelOrderId());
                model.setSubject("支付订单" + queryByOrderNo.getChannelOrderId());
                model.setTotalAmount(price);
                model.setBody(body);
                model.setTimeoutExpress("2m");
                model.setProductCode("QUICK_MSECURITY_PAY");
                alipay_request.setBizModel(model);


                // 设置异步通知地址
                alipay_request.setNotifyUrl(
                        (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.ALIPAY_NOTIFY_URL));
                // 设置同步地址
                alipay_request.setReturnUrl("http://renrenpin.shop/#/pages/my/order/order?idx=0");
                AlipayTradeAppPayResponse alipayTradeAppPayResponse = client.sdkExecute(alipay_request);
                // 就是orderString 可以直接给APP请求，无需再做处理。
                String orderString = alipayTradeAppPayResponse.getBody();
                log.error(orderString);
                respVo.setResult(orderString);
                respVo.setCode(0);
                OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(queryByOrderNo.getChannelOrderId()).queryTimes(0L).build();
                orderQueryMQ.setPayType(PayType.alipay);
                orderQueryMQ.setBody(body);
                orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            }
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用支付宝发起支付请求异常");
            log.error("支付宝拉起失败", e);
        }
        return respVo;
    }
    @ApiOperation(value = "订单查询")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/orderQuery")
    @ResponseBody
    public RespVo orderQuery(HttpServletRequest request, HttpServletResponse response, String orderNum, String orderId) {
        RespVo respVo = new RespVo();
        ShopOrder order = shopOrderService.queryByPayOrderNo(orderNum);
        if(StringUtils.isBlank(order.getPayMsg())){
            order.setPayMsg(orderId);
            shopOrderService.updateById(order);
        }
        respVo.setResult(order.getOrderPrice());
        if(order.getStatus().intValue() == 0 || order.getStatus().intValue() == 1 ){
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("待支付");
        }else{
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("支付成功");
        }
        return respVo;
    }
    @Autowired
    WxPayService wxPayService;
    @ApiOperation(value = "商城订单微信支付", httpMethod = "POST")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/wxPay")
    @ResponseBody
    public RespVo wxPay(String orderNum, String client, HttpServletRequest request) {
        RespVo respVo = new RespVo();
        try {
            BigDecimal price = BigDecimal.ZERO;
            String body = "SHOPPING";
            ShopOrder queryByOrderNo = shopOrderService.queryByPayOrderNo(orderNum);
            price = queryByOrderNo.getOrderPrice();
            queryByOrderNo.setChannelOrderId(idGeneratorService.genCommonIdString());
            shopOrderService.updateById(queryByOrderNo);

            //取库中微信参数
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "wxPaySys").eq(SysConfig::getDisplayStatus, "1"));
            List<ShopOrderDetail> shopOrderDetailList = shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId,queryByOrderNo.getId()));
            BigDecimal multiply = price.multiply(new BigDecimal("100"));
            String notifyUrl = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.WX_NOTIFY_URL);
            JsApiPay jsApiPay = new JsApiPay(null, multiply.intValue(), sysConfig.getValidateRules(), sysConfig.getConfigValue(),
                    notifyUrl, sysConfig.getConfigRules(), "", "APP");
            WxPayData wxData = jsApiPay.GetUnifiedOrderResult(shopOrderDetailList.get(0).getProductName(), "交易编号：" + orderNum, queryByOrderNo.getChannelOrderId(), body,CnswhyUtil.getHttpServletRequestIpAddress());
            if (StringUtils.equals(wxData.GetValue("return_code").toString(), "SUCCESS")
                    && StringUtils.equals(wxData.GetValue("result_code").toString(), "SUCCESS")) {
                Date beijingDate = Calendar.getInstance(Locale.CHINA).getTime();
                String timeStamp = String.valueOf(beijingDate.getTime() / 1000);
                SortedMap<String, Object> map2 = new TreeMap<String, Object>();
                map2.put("appid", sysConfig.getConfigValue());
                map2.put("timestamp", timeStamp);
                map2.put("noncestr", wxData.GetValue("nonce_str"));
                map2.put("prepayid", wxData.GetValue("prepay_id"));
                map2.put("package", "Sign=WXPay");
                map2.put("partnerid", wxData.GetValue("mch_id"));
                String paySign = WxPayApi.createSign(map2, sysConfig.getConfigRules());
                map2.put("sign", paySign);
                respVo.setCode(RespVo.CODE_SUCCESS);
                respVo.setResult(map2);
                OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(queryByOrderNo.getChannelOrderId()).queryTimes(0L).build();
                orderQueryMQ.setPayType(PayType.wx);
                orderQueryMQ.setBody("SHOPPING");
                orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            } else {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("发起微信支付失败");
            }
        } catch (Exception e) {
            log.error("调用微信支付请求异常：", e);
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("发起微信支付失败");
        }

        return respVo;
    }

    public RespVo saveOrder(MakeOrderBo bo) {
        RespVo respVo = new RespVo(RespVo.CODE_SUCCESS, "下单成功");

        // 用于异常回滚redis库存的map
        Map<Long, Long> returnRedisMap = new HashMap<>();
        try {
            // 生成支付订单号
            String payOrderNo = "P" + idGeneratorService.genCommonIdString();
            // 商家订单id集合
            StringBuffer redisIds = new StringBuffer();
            // 要移除购物车中的列表
            List<BuyerOperateBo> clearBuyerList = new ArrayList<BuyerOperateBo>();

            // 获取购物商品项
            BuyerCart buyerCart = shopOrderService.getBuyerCart(bo.getBuyerList(), bo.getReceiver());

            Customer customer = bo.getCustomer();
            CustomerWallet customerWallet = null;

            BigDecimal totalPrice = BigDecimal.ZERO;
            // 循环不同商家订单
            BuyerMerchant buyer = buyerCart.getMerchants().get(0);
            List<ShopOrderDetail> detailList = new ArrayList<ShopOrderDetail>();

            // 封装商家订单对象
            ShopOrder entity = new ShopOrder();
            entity.setCustomerId(bo.getCustomerId());
            entity.setMerchantId(buyer.getMerchantId());
            entity.setOrderNo(idGeneratorService.genCommonIdString());
            entity.setStatus(1);
            entity.setPayType(bo.getPayType());
            entity.setPayOrderNo(payOrderNo);
            // 计算运费
            entity.setFreightPrice(buyer.getSubFreightPrice());

            // 循环取出商品
            List<BuyerItem> items = buyer.getItems();
            for (BuyerItem item : items) {
                // 查询库存详情
                ShopProductStock stock = shopProductStockService.getById(item.getSku().getStockId());
                if (stock == null) {
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("抱歉，该规格无库存");
                    return respVo;
                }

                // 查询产品详情
                ShopProduct product = shopProductService.getById(stock.getProductId());
                if (product == null || product.getStatus().intValue() == 2) {
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("抱歉，该商品已下架");
                    return respVo;
                }


                try {
                    productStockService.subStock(stock.getId(),Long.valueOf(item.getNum()));
                } catch (BizException e) {
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("抱歉，库存不足");
                    return respVo;
                } catch (Exception e){
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("系统繁忙，请稍后重试");
                    return respVo;
                }
                // 记录redis扣减状态，若发生异常时，还需将扣减值归还
                returnRedisMap.put(stock.getId(), (long)item.getNum());


                if(entity.getPayType().intValue() == 6){
                    //余额支付
                    if (!walletService.checkDed(customer.getId(), WalletType.BALANCE, CnswhyUtil.getFen(entity.getOrderPrice()))) {
                        respVo.setCode(RespVo.CODE_ERROR);
                        respVo.setMessage("余额不足");
                        return respVo;
                    }
                }

                //walletService.ded(customer.getId(), WalletType.DEFAULT, TransType.SHOP_ORDER, CnswhyUtil.getFen(order.getOrderPrice()), order.getOrderNo());

                // 封装订单详情对象
                ShopOrderDetail detail = new ShopOrderDetail();
                detail.setStockId(item.getSku().getStockId());
                detail.setNum(item.getNum());
                detail.setProductId(product.getId());
                if(StringUtils.isNotBlank(stock.getUrl())){
                    detail.setProductImg(stock.getUrl());
                }else if(StringUtils.isNotBlank( stock.getImgUrl() )){
                    detail.setProductImg((String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX) +  stock.getImgUrl() );
                }else{
                    detail.setProductImg((String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX) +  product.getThumbnailImg() );

                }
                detail.setProductName(product.getProductName());
                detail.setCostPrice(item.getSku().getPrice());
                detail.setProductNo(product.getId() + "");
                detail.setSpecValues(stock.getSpecValues());
                detail.setStatus(0);
                detail.setUrl(stock.getUrl());
                detail.setAmount(item.getSku().getPrice().multiply(new BigDecimal(item.getNum())));
//                if(bo.getUseIntegral().compareTo(BigDecimal.ZERO) > 0) {
//                    detail.setDeductionIntegral(bo.getUseIntegral());
//                }
                detailList.add(detail);

                totalPrice = totalPrice.add(detail.getAmount());

                // 设置订单总额
                entity.setOrderPrice(totalPrice.add(buyer.getSubFreightPrice()));

                // 减数据库库存
                /*ShopProductStock updateStock = new ShopProductStock();
                updateStock.setId(item.getSku().getStockId());
                updateStock.setStock(value);
                shopProductStockService.updateById(updateStock);*/

                shopOrderService.save(entity);
                if(entity.getPayType() == 6){
                    //余额支付
                    //walletService.ded(customer.getId(), WalletType.BALANCE, TransType.SHOP_ORDER, CnswhyUtil.getFen(entity.getOrderPrice()), entity.getOrderNo());
                    entity.setStatus(2);
                    shopOrderService.saveOrUpdate(entity);
                }
                //customerService.save(customer);
                // 查询收货信息
                CustomerReceiver receiver = bo.getReceiver();
                // 保存收货人详情
                if (receiver != null) {
                    //receiver.setOrderId(entity.getId());
                    shopOrderService.insertReceiver(receiver,entity.getId());
                }

                // 保存订单详情
                if (CollUtil.isNotEmpty(detailList)) {
                    for (ShopOrderDetail detail1 : detailList) {
                        detail1.setOrderId(entity.getId());
                        shopOrderDetailService.save(detail1);
                    }
                }
                //更新销量
                int sellNum = product.getSellNum() == null ? 0 : product.getSellNum();
                product.setSellNum(sellNum + item.getNum());
                shopProductService.updateById(product);
                // 将待付款订单放入redis，超过订单时间自动过期，格式：订单日期_商户订单id
                redisService.hset(RedisConstant.SHOP_PRODUCT_ORDER, entity.getId() + "",
                        DateUtil.now() + "_" + entity.getId());

                // 保存订单
                if (redisIds.length() != 0) {
                    redisIds.append(",");
                }
                redisIds.append(entity.getId());
            }
//            if (bo.getType().equals(1))
//            {
//                this.removeRedisCartItem(clearBuyerList, bo.getCustomerId());
//            }

            // 将支付订单与商户订单关系放入redis中，格式：商户订单id,商户订单id|金额
            redisService.hset(RedisConstant.SHOP_PRODUCT_PAY_ORDER, payOrderNo,
                    redisIds.append("|").append(buyerCart.getTotalPrice()).toString());

            respVo.setResult(payOrderNo);
        } catch (Exception e) {
            // 若redis中库存已被扣除，但后续出现异常，则回滚redis库存
            if (!returnRedisMap.isEmpty()) {
                try {
                    Set<Map.Entry<Long, Long>> set = returnRedisMap.entrySet();
                    for (Map.Entry<Long, Long> entry : set) {
                        productStockService.addStock(entry.getKey(),entry.getValue());
                    }
                } catch (Exception e2) {
                    log.error("名品名店下单时发生异常，redis库存回滚时发生异常：", e2);
                }
            }
            log.error("名品名店下单时发生异常，异常原因：", e);

            // 抛出运行异常，用于触发事务回滚数据库
            throw new RuntimeException();
        }
        return respVo;
    }

    @ApiOperation(value = "查询支付方式", httpMethod = "POST")
    @ApiParam(name = "sysConfig", value = "系统参数对象")
    @RequestMapping("/queryPayType")
    @ResponseBody
    public RespVo queryPayType(@RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                               @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        RespVo respVo = new RespVo();
        try {
            SysConfig sysConfig = new SysConfig();
            sysConfig.setConfigValue("payType");
            sysConfig.setDisplayStatus("1");
            QueryWrapper<SysConfig> queryWrapper = QueryGenerator.initQueryWrapper(sysConfig);
            queryWrapper.orderByDesc("id");
            Page<SysConfig> page = new Page<>(currentPage, pageSize);
            IPage<SysConfig> pageList = sysConfigService.page(page, queryWrapper);

            respVo.setResult(pageList);
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("失败");
            log.error("查询支付方式异常：", e);
        }
        return respVo;
    }

    @ApiOperation(value = "商城订单余额支付")
    @RequestMapping("/DEFAULTPay")
    @ResponseBody
    public RespVo DEFAULTPay(HttpServletRequest request, HttpServletResponse response, String orderNum, String tradePass) {
        log.info("商城订单余额支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            ShopOrder order = shopOrderService.queryByPayOrderNo(orderNum);
            if (StringUtils.isEmpty(tradePass)) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("请输入交易密码");
                return respVo;
            }
            Customer loginCustomer = getLoginCustomer( request);
            Customer customer = customerService.queryById(loginCustomer.getId());
            String password = null;
            password = RSAUtils.decryptString(tradePass);// 解密
            if (!StringUtils.equals(PasswordCoder.generatePassword(password), customer.getTradePass())) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("交易密码错误");
                return respVo;
            }
            CustomerWallet customerWallet = walletService.checkAndCreate(customer.getId(), WalletType.BALANCE, 0L);
            if (!walletService.checkDed(customerWallet.getCustomerId(), WalletType.BALANCE, CnswhyUtil.getFen(order.getOrderPrice()))) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("余额不足");
                return respVo;
            }
            //walletService.ded(customer.getId(), WalletType.BALANCE, TransType.SHOP_ORDER, CnswhyUtil.getFen(order.getOrderPrice()), order.getOrderNo());

            order.setStatus(2);
            shopOrderService.saveOrUpdate(order);
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("支付成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用余额支付请求异常");
            log.error("调用余额支付请求异常", e);
        }
        return respVo;
    }

}
